package hotel.dao;

import hotel.tipos.Entrada;
import hotel.tipos.Reserva;
import hotel.util.HibernateUtil;

import java.util.Date;
import java.util.LinkedList;
import java.util.List;

import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;

public class EntradaDao {
	public static int create(Entrada in) throws Exception{
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
				
				session.beginTransaction();
				
				// in.setHospedeId(HospedeDao.buscarHospede(in.getHospedeId().getId()));
				
				//in.getAp().setTipo(TipoApartamentoDao.buscarAp(in.getAp().getTipo().getId()));

		        Integer id = (Integer) session.save(in);
		        
		        session.getTransaction().commit();
		        
		        return id.intValue();
			}
	
	public static boolean delete(Entrada in){
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
				
				session.beginTransaction();
				
				// in.setHospedeId(HospedeDao.buscarHospede(in.getHospedeId().getId()));

				try{
					session.delete(in);
					session.getTransaction().commit();
				} catch (HibernateException e){
					e.printStackTrace();
					return false;
				}
		        
		        return true;
			}
	
			/**
			 * Retorna a entrada que está utilizando o apartamento na data atual ou null caso o ap esteja vazio
			 * @param ap Numero do apartamento a ser checado
			 * @return a entrada que está utilizando o apartamento na data atual ou null caso o ap esteja vazio
			 */
			public static Entrada checkOcupation(int ap){
				// Cria uma sessão
				Session session = HibernateUtil.getSessionFactory().getCurrentSession();
				// inicia a transação
				session.beginTransaction();
									// SQL select e.*  from apartamento ap, entrada e 
									// where ap.Id = 1 and ap.Id = e.apId and 
									// (select e1.id from entrada e1 where e1.apId = ap.Id and 
									// ((e1.dataInicio >= '2010-03-01' and e1.dataInicio <= '2010-03-06') 
									//   or (e1.dataFim >= '2010-01-03' and e1.dataFim <= '2010-03-06')));
				
				String query = new String(" select e from Apartamento ap, Entrada e " +
											"WHERE ap.numero = :apId AND e.ap.id = ap.id AND " +
											"(SELECT e1.id FROM Entrada as e1 " +
												"WHERE e1.ap.numero = :apId AND " +
												"((e1.dataInicio >= :dtIn AND e1.dataInicio <= :dtOut) " +
												"  OR (e1.dataFim >= :dtIn AND e1.dataFim <= :dtOut))) is not null");
				
				
				Query q = session.createQuery(query);
				q.setDate("dtIn",new Date());
				q.setDate("dtOut",new Date());
				q.setInteger("apId", ap);
				
				List<Entrada> e = q.list();
				
				if (e.size()>0)
					return e.get(0);
				else
					return null;
			}
			
			
			/**
			 * Retorna se o apartamento esta livre na data solicitada
			 * @param in Entrada com os dados do apartamento a procurar
			 * @return true se o apartamento esta livre na data solicitada ou false caso contrário
			 */
			public static boolean checkOcupation(Entrada in){
				// Cria uma sessão
				Session session = HibernateUtil.getSessionFactory().getCurrentSession();
				// inicia a transação
				session.beginTransaction();
									// SQL select e.*  from apartamento ap, entrada e 
									// where ap.Id = 1 and ap.Id = e.apId and 
									// (select e1.id from entrada e1 where e1.apId = ap.Id and 
									// ((e1.dataInicio >= '2010-03-01' and e1.dataInicio <= '2010-03-06') 
									//   or (e1.dataFim >= '2010-01-03' and e1.dataFim <= '2010-03-06')));
				
				String query = new String(" select e.id from Apartamento ap, Entrada e " +
											"WHERE ap.id = :apId AND e.ap.id = ap.id AND " +
											"(SELECT e1.id FROM Entrada as e1 " +
												"WHERE e1.ap.id = :apId AND " +
												"((e1.dataInicio >= :dtIn AND e1.dataInicio <= :dtOut) " +
												"  OR (e1.dataFim >= :dtIn AND e1.dataFim <= :dtOut))) is not null");
				
				/**
				 * String query = new String(" SELECT e.id FROM Entrada e join e.ap as ap " +
											"WHERE ap.id = :apId AND ap = e.ap AND " +
											"(SELECT e1.id FROM Entrada e1 " +
												"WHERE e1.ap = ap AND " +
												"((e1.dataInicio >= :dtIn AND e1.dataInicio <= :dtOut) " +
												"  OR (e1.dataFim >= :dtIn AND e1.dataFim <= :dtOut)))");
				 */
				
				
				Query q = session.createQuery(query);
				q.setDate("dtIn",in.getDataInicio());
				q.setDate("dtOut",in.getDataFim());
				q.setInteger("apId", ApartamentoDao.apartamentoNumero(in.getAp().getNumero()).getId());
				// System.out.println("dataIn = "+in.getDataInicio());
				// System.out.println("dataOut = "+in.getDataFim());
				// System.out.println("apId = "+in.getAp().getId());
				
				List<Entrada> e = q.list();
				
				if (e.size()>0)
					return false;
				else
					return true;
			}
	
			@SuppressWarnings("unchecked")
			public static LinkedList<Entrada> listarEntradas() {
				// Cria uma sessão
				Session session = HibernateUtil.getSessionFactory().getCurrentSession();
				// inicia a transação
				session.beginTransaction();
				// Cria uma lista para retornar
				LinkedList<Entrada> entradas = null;
				
				try{
					entradas = new LinkedList<Entrada>(session.createQuery("from Entradas").list());
				} catch (Exception e) {
					e.printStackTrace();
				}
				
				return entradas;
			}
			
			public static Reserva procuraReserva(Reserva r){
				// Cria uma sessão
				Session session = HibernateUtil.getSessionFactory().getCurrentSession();
				// inicia a transação
				session.beginTransaction();
				// Cria uma reposta:
				Reserva re;
				
				String query = new String("select r from Reserva r where r.dataInicio = :dtIni and r.hospedeId.cpf = :cpf");
				Query q = session.createQuery(query);
				q.setDate("dtIni",r.getDataInicio());
				q.setString("cpf", r.getHospedeId().getCpf());
				
				try{
					re = (Reserva) q.list().get(0);
				} catch (IndexOutOfBoundsException ie){
					re = null;
				}
				
				return re;
			}
}
